package web

import (
	"errors"
	"fmt"
	"gitee.com/tools/internal/service"
	"gitee.com/tools/internal/web/tools/common"
	"github.com/gin-gonic/gin"
	"net/http"
	"strconv"
	"strings"
	"time"
)

type Tools struct {
	svc service.TcpService
}

func NewTools(svc service.TcpService) *Tools {
	return &Tools{
		svc: svc,
	}
}
func (t *Tools) Router(r *gin.Engine) {
	g := r.Group("/tools")
	g.POST("/portscan", t.PortScan)
}

func (t *Tools) PortScan(ctx *gin.Context) {
	type Info struct {
		Addr     string `json:"addr"`
		Port     string `json:"port"`
		Duration int    `json:"duration"`
	}
	var info Info
	if err := ctx.BindJSON(&info); err != nil {
		ctx.JSON(http.StatusBadRequest, common.Result{
			Code:    common.ErrorUserInputInvalid,
			Message: "参数不合法",
			Data:    nil,
		})
		return
	}
	portlist, err := ParseParams(info.Port)
	if err != nil {
		ctx.JSON(http.StatusOK, common.Result{
			Code:    common.ErrorUserInputInvalid,
			Message: "参数不合法",
			Data:    nil,
		})
		return
	}
	dura, err := time.ParseDuration(fmt.Sprintf("%dms", info.Duration))
	if err != nil {
		ctx.JSON(http.StatusBadRequest, common.Result{
			Code:    common.ErrorUserInputInvalid,
			Message: "参数不合法",
			Data:    nil,
		})
		return
	}
	open, cls, err := t.svc.Scan(ctx, info.Addr, portlist, dura)
	if err != nil {
		ctx.JSON(http.StatusOK, common.Result{
			Code:    common.ErrSystem,
			Message: "系统错误",
			Data:    nil,
		})
		return
	}
	ctx.JSON(http.StatusOK, common.Result{
		Code:    0,
		Message: "扫描完成",
		Data: map[string][]int{
			"open":  open,
			"close": cls,
		},
	})
	return
}

func ParseParams(port string) ([]string, error) {
	parts := strings.Split(port, ",")
	result := make([]string, 0)
	for _, part := range parts {
		if containDash(part) {
			rangeParts := strings.Split(part, "-")
			start, err := strconv.Atoi(rangeParts[0])
			if err != nil || start <= 0 {
				return nil, errors.New("起始端口错误")
			}
			end, err := strconv.Atoi(rangeParts[1])
			if err != nil || end > 65535 {
				return nil, errors.New("结束端口错误")
			}
			if start > end {
				return nil, errors.New("起始端口大于结束端口")
			}
			for i := start; i <= end; i++ {
				result = append(result, strconv.Itoa(i))
			}
		} else {
			num, err := strconv.Atoi(part)

			if err != nil || num > 65535 || num <= 0 {
				return nil, errors.New("端口错误")
			}
			result = append(result, strconv.Itoa(num))
		}
	}
	return result, nil
}

func containDash(s string) bool {
	return strings.Contains(s, "-")
}
